
// ===============================================================================================================
// -*- C++ -*-
//
// Math.hpp - Fast mathematical routines used throughout the application.
//
// Copyright (c) 2011 Guilherme R. Lampert
// guilherme.ronaldo.lampert@gmail.com
//
// This code is licenced under the MIT license.
//
// This software is provided "as is" without express or implied
// warranties. You may freely copy and compile this source into
// applications you distribute provided that the copyright text
// above is included in the resulting source code.
//
// ===============================================================================================================

#ifndef __MATH_HPP__
#define __MATH_HPP__

namespace Math {

// =========================================================
// Usefull Mathematical Constants
// =========================================================

extern const float PI;         ///< 4*atan(1)
extern const float TWO_PI;     ///< 2*pi
extern const float HALF_PI;    ///< pi/2
extern const float INV_PI;     ///< 1/pi
extern const float INV_TWO_PI; ///< 1/(2*pi)
extern const float DEG_TO_RAD; ///< pi/180
extern const float RAD_TO_DEG; ///< 180/pi

// =========================================================
// Trigonometry - All Angles Are In Radians!
// =========================================================

/// Sine of angle in radians.
float Sine(float x);

/// Cosine of angle in radians.
float Cosine(float x);

/// Computes the sine and cosine of the angle using a single FP instruction if available.
void SineCosine(float ang, float & s, float & c);

/// Arc sine. Clamp the input to [-1,1] to avoid NAN issues.
/// \return Arc sine of x, in the interval [-pi/2,+pi/2] radians.
float ArcSine(float x);

/// Arc cosine. Clamp the input to [-1,1] to avoid NAN issues.
/// \return Principal arc cosine of x, in the interval [0,pi] radians.
float ArcCosine(float x);

/// Tangent of angle in radians.
float Tangent(float x);

/// Returns angle between [-pi/2,+pi/2] radians.
float ArcTangent(float x);

/// Arctangent of (x/y) with correct sign. Returns angle between [-pi,+pi] radians.
float ArcTangent(float x, float y);

/// Computes the hypotenuse of x and y.
float Hypotenuse(float x, float y);

// =========================================================
// Floating Point Arithmetics
// =========================================================

/// Square root.
float Sqrt(float x);

/// Inverse square root. (Reciprocal square root).
float InvSqrt(float x);

/// Returns a decimal value representing the smallest integer that is greater than or equal to x. 
float Ceil(float x);

/// Returns a decimal value representing the largest integer that is less than or equal to x.
float Floor(float x);

/// Truncates the decimal value to an integer.
int Truncate(float x);

/// Checks if the value is NAN.
bool IsNAN(float x);

// =========================================================
// Random Numbers
// =========================================================

/// Seeds the random number generator with the current time.
void SeedRandomGenerator(void);

/// Generates a random number in the range of [0,1].
float UniformRandom(void);

/// Generates a random number in the range of [min,max].
int RandomNumber(int min, int max);

// =========================================================
// Templates / Inline Routines
// =========================================================

/// Absolute value of x.
template<typename T> static inline T Abs(T x)
{
	return ((x < T(0)) ? -x : x);
}

/// Minimum value between a and b.
template<typename T> static inline T Min(T a, T b)
{
	return ((a < b) ? a : b);
}

/// Maximum value between a and b.
template<typename T> static inline T Max(T a, T b)
{
	return ((a > b) ? a : b);
}

}; // namespace Math {}

#endif // __MATH_HPP__